ミディアムFORTH M−FORTH/MZ ――――――――――――――――――――――――――――――――――――――― I/O 1981年 3月号掲載 MZ−80 マシン語 01200H−0264FH S:01200H 起動方法 モニタからロード コールド・スタート 01200H ウォーム・スタート 01268H           01925H(テキストディタから起動) ――――――――――――――――――――――――――――――――――――――― FORTHは1969年頃、 チャールズ・H・ムーア氏によって考案された言語で、 氏自らで設立したFORTH社で扱われているものです (なお、FORTHはFORTH社の登録商標です) こにの言語はBASIC、FORTRANなどと比較したとき 非常にユニークな特徴を持っています。 その特徴としては、 (1)自己増殖型の言語であること。   あるプログラムを作ったとき、   それはFORTHであらかじめ準備されたワード(語)と   まったく同等なものとなり、   プログラミングはFORTHの機能を拡張することになる。 (2)ルーチンのデータの受け渡しにスタックが使用されること。   このため、代入文がなく、演算が逆ポーランド型式で記述される。   この逆ポーランド型式の記述は日本語の表現によく合うもので、   たとえば、1+2は逆ポーランド型式では   1 2+(1に2を加える)と書かれる   (1+2は『1たす2』というが、    これは本来の日本語では不自然なものである)。 (3)プログラミングは対話型式で実行され、構造化プログラミングが可能である。 (4)再帰的手続きを記述できる。 (5)オブジェクト構造が単純で、インタープリタが小さい。 (6)きめ細かい操作が記述できる。 などがあります。 この他、本来のFORTHはアセンブラ内蔵などの特徴がありますが、 M−FORTH V1.1ではアセンブラは作っていません。 M−FORTH V1.1はMZ−80本体のみで 使用できるように機能を制限し、 また、擬似グラフィック機能が 充分活用できるような機能を追加して 作成されたものです。 ・―――――――――――――――――・ |■■■必■要■機■器■構■成■■■| ・―――――――――――――――――・ MZ−80本体 メモリ20Kバイト以上、モニタは SP-1002。 M−FORTH 1本、カウンタ30からDEMOが入っています。 TXT[CR] ⇒ L[CR] ⇒ F[CR] ⇒ ![CR] ⇒ DEMO[CR] (テキスト・モードへ)  (ロード)  (コンパイル)   (メインへ)   (DEMOを実行) ・―――――――――――――――――・ |■■■■■■使■用■法■■■■■■| ・―――――――――――――――――・ 1)モニタでカセットからロードします。   ・―――――――――――――――――・   | *LOAD           |   ・―――――――――――――――――・   ロードが完了すると次の表示が出ます。   ・――――――――――――――――――――――・   |■MIDIAM FORTH V1.1 ■ MEM=hhhh1,hhhh2   |   |#■←(カーソル)              |   ・――――――――――――――――――――――・   ここで、hhhh1 はリターン・スタックのBOTTOMアドレスで、   メモリの実装量から8Kバイト小さい値が表示されます   (48KではAFFF、32Kでは6FFFF、20Kでは3FFFです)。   hhhh2 はデータ・スタックのBOTTOMアドレスで、   リターン・スタックのBOTTOMと辞書の最後との中間点に設定されます。 2)#プロンプトの後に(#プロンプトはなくてもよい)、   FORTHのワード、または定数を空白(スペース)を   区切り文字に使って入力します(CRではない)。 ・―――――――――――――――――・ |■■■■■メモリ・マップ■■■■■| ・―――――――――――――――――・ 1)PEは$1506、DSは$150E、SPは$1512、   VVRは$1514からの2バイトに各々のアドレスが入っています。   DS、SPは語LIMITで変更します。   VVR($1514)を変えて、   仮想V−RAMの位置を変更することもできます。 2)スタート・アドレス ●コールド・スタート$1200  DS、SP、VVRが使用法の1)で示したように初期化されます。  ソース・テキストは消滅しますが、辞書(オプ`ジェクト)は変化しません。 ●ウォーム・スタート$1268   リターン・スタックだけがクリアされた状態からスタートします。  データ・スタック、ソース・テキストなどは変化しません。 ●ウォーム・スタート$1925  テキスト・エディタから起動します。  1200→・――――――――――・       |(メイン)     |       | インタープリタ  |  15B9→|――――――――――|       |乗除算、グラフィック|       |CORDICサブルーチン |  1925→|――――――――――|       |  テキスト・   |       |   エディタ   |  1CDA→|――――――――――|       |          |       |    辞書    |       |          |  PE  →|――――――――――|       |  ↓ 辞書拡張  |       |          |       |    データ・  |       |  ↑ スタック  |  DS  →|――――――――――|       |  ↓文字ストリング|       |   ・エリア   |       |          |       |   リターン・  |       |  ↑ スタック  |  SP  →|――――――――――|       |■■↓■■■■■■■|       |■■■■■■■■■■|       |■ソース・テキスト■|  VVR →|――――――――――|       |  仮想VRAM  |}1Kバイト       ・――――――――――・ ・―――――――――――――――――・ |■■■■■サブルーチン■■■■■■| ・―――――――――――――――――・ ・――――――――――――――――――――――――――・ |サブルーチン 名|アドレス |     機    能     | |―――――+―――+――――――――――――――――| |MULT   |$160F |乗算:DEXBC→HLDE(符号なし  | |     |   |   16ビット×16ビット→32ビット) | |DIV0  |$15FA |除算 HLDE÷BC(商)、HL(余り) | |     |   |   (符号なし)       | |CODR   |$1820 |CORDIC回転モード補正付き    | |     |   |(x→BC、y→DE、z=HL)    | |CODV   |$188D |CORDICベクトル・モード補正付き   | l     |   |(x→BC、y→DE、z=HL)    | |SETGS  |$1654 |擬似グラフィックSETサブルーチン      | |RESGS  |$1670 |  〃  RESET 〃       | |LINESB  |$16F6 |  〃  LINE  〃       | ・――――――――――――――――――――――――――・ ・―――――――――――――――――・ |M-FORTH で入力できる文字列の種類■| ・―――――――――――――――――・ ・―ワード(語):FORTHの辞書に登録された手続きなどの名前 |        (名前の文字数は79字まで) | |        ・―(±) n…n:変数、BASEの値に基づく進法表現 |   ・―数定数| (±)$n…n:16進数 |   |    ・―(±)#n…n:10進数 ・―定数|       |     ・―文字定数”××××” ××××は1文字以上 数字は10進で-32,768〜+32,767までの整数が扱えます。 ・―――――――――――――――――・ |■■■M−FORTHの構造■■■■| ・―――――――――――――――――・  1)辞書の構造       2)ワードの構造   ・―――――――・     ・――――――――――・   | $FFFF |     |ポインタ(2バイト)|   |―――――――|     |名前の文字数(1B)|   |::ポインタ::::|\    |--------------------|   |--------------| |   |          |   |ワードの名前 | |   |          |   |--------------| |ワード |ワードの名前(不定)|   |       | |   |          |   |ワードの定義 | |   |          |   |       | |   |――――――――――|   |―――――――|/    |ワードの属性(1) |   |::ポインタ::::|\    |--------------------|   |--------------| |   |          |   |       | |ワード | ワードの定義内容 |   =       = |   |          |   |       | |   ・――――――――――・   |―――――――|/   |::ポインタ::::|\   |--------------| |ワード   |       | |   |       |/   |―――――――|    |::ポインタ::::|  ・→・―――――――・ |    $1506 | ・―――――――・ ・―|       |   ・―――――――・ 3)データ・スタック  |     |       例)[ABS DUP0   | F0 |if 2nd>TOP then -1 → TOP else 0 → STOP | | | | | 例)2 2 >:TOPは0 | |―+―――――+――+――――――――――――――――――――――――――| | |CORDR | F0 |3rd:x、2nd:y、TOP:z とするとき | |座|    |  |x cos z - y sin z →2nd, x sin z + y cos z- | |標|    |  | → TOP(xの単位は0.5°) | |回|    |  |例)1000 0 60 CORDR:2ndは866(10000cos30°)、 | |転|    |  |TOPは500(1000sin30°) | |・|―――――+――+――――――――――――――――――――――――――| |倫|CORDV | F0 |ルートx^2+y^2 →2nd、x+tan^-1 y/x→TOP | |理|    |  | (x(3rd)≧0であること) | |演|    |  |例)866 500 0 CORDV | |算|    |  | :2ndは1000(ルート866^2+500^2、TOPは60(30°)| |―+―――――+――+――――――――――――――――――――――――――| | |STK | F0 |スタックの内容をTOPからBOTTOMまで。出力形式で表示する | | |  |  |(TOP=1、2nd=2、3rd=3、4th=4、5th=5まで | | | |  | スタックに入っているときのスタックの変化を | | | |  | 以下では例とする)。 | |ス| |  |STKを実行したとき1 2 3 4 5が表示される。 | | |―――――+――+――――――――――――――――――――――――――| |タ|CLR  | F6 |スタックを空にする。 | | |―――――+――+――――――――――――――――――――――――――| |ッ|DUP | F0 |TOPを複製する。 1 1 2 3 4 5 | | |―――――+――+――――――――――――――――――――――――――| |ク|DDUP | F0 |TOP、2ndを複製する。 1 2 1 2 3 4 5 | | |―――――+――+――――――――――――――――――――――――――| |操|OVER | F0 |2ndを複製する。     2 1 2 3 4 5 | | |―――――+――+――――――――――――――――――――――――――| |作|2OVER | F0 |3rdを複製する。     3 1 2 3 4 5 | | |―――――+――+――――――――――――――――――――――――――| | |3OVER | F0 |4thを複製する。     4 1 2 3 4 5 | | |―――――+――+――――――――――――――――――――――――――| | |SWAP | F0 |TOPと2ndを交換する。 2 1 3 4 5 | | |―――――+――+――――――――――――――――――――――――――| | |DROP | F0 |TOPを取り去る。     2 3 4 5 | | |―――――+――+――――――――――――――――――――――――――| | |ROT | F6 |スタックのBOTTOMをTOPに移す。 5 1 2 3 4 | |―+―――――+――+――――――――――――――――――――――――――| | |@ | F0 |TOPの値をメモリのアドレスとしてメモリの内容2バイトを | | | |  |TOPに入れる。 | | | | |例)$1000 @:TOPには($1001),($1000)の | | | |  | 2バイトの内容が入る。| |メ|     |  | A @:Aが変数のとき、変数の内容がTOPに入る。 | | |―――――+――+――――――――――――――――――――――――――| |モ|@B  | F0 |@の転送内容を1バイトにしたもの内容は | | | |  |     下位バイトに入る上位バイトは0(PEEK)。| |リ|―――――+――+――――――――――――――――――――――――――| | |! | F0 |TOPの値をメモリのアドレスとして2ndの内容2バイトに移す。 | |・|   |  |例)$1234 $1000 !:$34→($1000)、$12→($1001) | | |   |  |  $1234 a !:Aを変数とするとき$1234をAに入れる。| |ア|―――――+――+――――――――――――――――――――――――――| | |!B | F0 |!の転送内容を2ndの下位1バイトにしたもの。 | |ク|―――――+――+――――――――――――――――――――――――――| | |MV+ | F0 |(3rd)から(2nd)へ(TOP)バイト、 | |セ| |  |アドレスをカウント・アップして転送する。 | | |   |  |例)$1000 $D000 $100 MV+ | |ス| |  | :($1000〜$10FF)→($D000〜$D0FF)| | |―――――+――+――――――――――――――――――――――――――| | |MV- | F0 |(3rd)から(2nd)へ(TOP)バイト、 | | | |  |アドレスをカウント・ダウンして転送する。 | | |    |  |例)$10FF $D0FF $100 MV- | | | |  | :($10FF〜$1000)→($D0FF〜$D000)| |―+―――――+――+――――――――――――――――――――――――――| | |IF | F6 |IF(TOP≠0のときの処理)ELSE (TOP=0のときの処理)THEN | |制|〜(ELSE) |  |例)0>IF "PLUS" ELSE "NOT PLUS" THEN S. | |御| |  | :TOPが正のときPLUS、      | | | |  |  正でないときNOT PLUSを表示する。| | |―――――+――+――――――――――――――――――――――――――| |直|F.IF | F6 |F.IF (TOP=0のときの処理) ELSE (TOP=0のときの処理) | |接|〜(ELSE〜)|  | THEN | |実|THEN |  |例)0=F.IF "NOT ZERO" S.THEN | |行| |  | :TOPが0でないときNOT ZEROを表示する。| |は|―――――+――+――――――――――――――――――――――――――| |で|DO〜LOOP | F6 |DO実行時の2ndを終値、TOPを初期として | |き| |  |LOOPでカウンタを+1して、結果が終値より小さければ | |な| |  |DOの次に戻り、終値以上であればLOOPの次に進む。 | |い|     |  |例)10 0 DO I . LOOP | |の| |  | :カウンタを0〜9まで変化させて『I.』を繰り返し実行する| |で|     |  |   (0123456789が表示される)。| |[|―――――+――+――――――――――――――――――――――――――| |の|BEGIN〜 | F6 |END実行時のTOPが0なら、BEGINの次に戻り、 | |中| |  |0でなければENDの次に進む。 | |で|END |  |例)BEGIN GETKY END:キーが何か押されるまで待つ。 | |使|―――――+――+――――――――――――――――――――――――――| |用|I | F6 |DO〜LOOPの中で使用し、カウンタの値をTOPに積む。 | |す|     |  |例)10 0 DO I . LOOP | |る|     |  |  10 0 DO BEGIN I . GETKY END LOOP | | | |  |:これは誤りである(IがBEGIN〜ENDの中で使われている)。| | |―――――+――+――――――――――――――――――――――――――| | |J | F6 |DO〜LOOP中で使用し、終値の値をTOPに積む。 | |―+―――――+――+――――――――――――――――――――――――――| | |SETG | F0 |2nd:x, TOP | | | |  |:yの位置にドットを表示する(0≦x≦79,0≦y≦49)。 | | |     |  |例)40 24 SETG | | |―――――+――+――――――――――――――――――――――――――| |グ|RESG   | F0 |2nd:x,TOP:yの位置のドットを消す | | | |  | (0≦x≦79,0≦y≦49)。| |ラ|     |  |例)40 24 RESG | | |―――――+――+――――――――――――――――――――――――――| |フ|LINE | F0 |4th:x1,3rd:y1と2nd:x2,TOP:y2を線(ドット)で結ぶ。 | | |     |  |例)0 0 79 49 LINE: | |ィ| |  | (0,0)から(79,49)に線を引く(対角線)。| | |―――――+――+――――――――――――――――――――――――――| |ッ|VRCL | F6 |仮想V-RAMをクリアし、仮想V-RAMスイッチをONにする。 | | |―――――+――+――――――――――――――――――――――――――| |ク|VRMV   | F6 |仮想V-RANスイッチがONなら、仮想V-RAMの内容をV-RAMに移し、| | | |  |仮想V-RAMスイッチをOFFにする。 | |ス|―――――+――+――――――――――――――――――――――――――| | |VRCH   | F6 |仮想V-RAMスイッチを切り換える。 | | | |  |仮想V-RAMスイッチがONのときはSETG、RESG、LINEは | | |     |  |仮想V-RAM上で実行され、CRT画面には現われない。 | | |     |  |初期値はOFF。 | |―+―――――+――+――――――――――――――――――――――――――| | |LIMIT | F6 |データ・スタック、リターン・スタックのBOTTOMのアドレスを変更する。 | | |     |  |2nd→データ・スタックのBOTTOMのアドレス、 | | |     |  |TOP→リターン・スタックのBOTTOMのアドレス。 | | |     |  |実行後、データ・スタック、リターン・スタックは空になり、 | | |     |  |インタープリタの初期状態に変える。 | |―+―――――+――+――――――――――――――――――――――――――| | |SAVE   | F6 |SAVE a…aでSAVE以降のFORTHオブジェクトを | | |     |  |a…a(16文字以内)の名前を付けてカセットに保存する。 | |―+―――――+――+――――――――――――――――――――――――――| | |LOAD | F6 |SAVEによって保存されたオブジェクトを | | |     |  |カセットからロードする(ファイル名はチェックしない)。 | |―+―――――+――+――――――――――――――――――――――――――| | |VERI | F6 |カセットのベリファイを行なう。OKときは何も出ない。 | | |     |  |エラーのときはVERIFY ERRを表示。 | |―+―――――+――+――――――――――――――――――――――――――| | |REG | F2 |変数USRのAF、BC、DE、HLの受渡し用エリア | | |     |  |配置:REG→|F|A|C|B|A|E|D|L|H| | |―+―――――+――+――――――――――――――――――――――――――| | |USR | F6 |TOPの値の指すアドレスヘサブルーチン・ジャンプする。 | | |     |  |ジャンプ時にREGのA、BC、DE、HLがレジスタに送られる。 | | |     |  |リターン時にはREGにAF、BC、DE、HLが返される。 | | |     |  |例)REG 1 + CONST AREG $30 AREG !B $12 USR | | |     |  |  :Aレジスタに$を入れてCALL $12を実行する| | | |  | (画面には0が表示される)。| |―+―――――+――+――――――――――――――――――――――――――| | |APLY | F6 |(2nd、TOP)を文字定数として、 | | | |  |その文字と一致するワードを実行する | | |     |  |(ワードがないときは何もしない)。 | | |     |  |例)3 4 "+" APLY:3 4 +と同じ | |―+―――――+――+――――――――――――――――――――――――――| | |BASE | F2 |数値入出力(入力時は$、#なしの数字、出力は。) | | | |  |における進法の基底、 | | |     |  |下位バイトのみが有効。初期値は10。 | | |     |  |例)$10 BASE !:入出力を16進数で行なう。 | |―+―――――+――+――――――――――――――――――――――――――| | |SP    | F5 |リターン・スタックのBOTTOMのアドレスが記憶されているメモリのアドレス | |―+―――――+――+――――――――――――――――――――――――――| | |DS | F5 |データ・スタックのBOTTOMのアドレスが記憶されているメモリのアドレス | |―+―――――+――+――――――――――――――――――――――――――| | |PE | F5 |辞書の追加エリアのアドレスが記憶されているメモリのアドレス | |―+―――――+――+――――――――――――――――――――――――――| | |TXT | F6 |テキスト・エディタにインタープリタから制御を移す。 | ・―――――――――――――――――――――――――――――――――――――・ ・―――――――――――――――――・ |■■■M−FORTH使用例■■■■| ・―――――――――――――――――・ まず、BASEの値は10とします。 (1)10 2 3 + * . 50が表示される(PRINT10*(2+3);に相当する)。    10    2    3    +    *    .   |  | |  | |  | |  | |  | |  |   |  | |  | |  | |  | |  | |  |   |  | |  | |  | |  | |  | |  |   |  | |  | |  | |  | |  | |  |   |  | |  | |――| |  | |  | |  |   |  |⇒| |⇒| 3 |⇒|  |⇒|  |⇒|  |   |  | |――| |――| |――| |――| |――|   |  | | 2 | | 2 | | 5 | |  | |  |   |――| |――| |――| |――| |――| |  |   | 10 | | 10 | | 10 | | 10 | | 50 | |  |   |――| |――| |――| |――| |――| |――|   |////| |////| |////| |////| |////| |////| (2)3 4 5 OVER DUP * SWAP / + - .   −4が表示される(PRINT3-(4+4*4/5);).     3    4    5   OVER    DUP    *   |  | |  | |  | |  | |――| |  |   |  | |  | |  | |  | | 4 | |  |   |  | |  | |  | |――| |――| |――|   |  | |  | |  | | 4 | | 4 | | 16 |   |  | |  | |――| |――| |――| |――|   |  |⇒| |⇒| 5 |⇒| 5 |⇒| 5 |⇒| 5 |   |  | |――| |――| |――| |――| |――|   |  | | 4 | | 4 | | 4 | | 4 | | 4 |   |――| |――| |――| |――| |――| |――|   | 3 | | 3 | | 3 | | 3 | | 3 | | 3 |   |――| |――| |――| |――| |――| |――|   |////| |////| |////| |////| |////| |////|   SWAP   /    +    ―    .   |  | |  | |  | |  | |  |   |  | |  | |  | |  | |  |   |――| |  | |  | |  | |  |   | 5 | |  | |  | |  | |  |   |――| |――| |  | |  | |  |   | 16 |⇒| 3 |⇒|  |⇒|  |⇒|  |   |――| |――| |――| |  | |  |   | 4 | | 4 | | 7 | |  | |  |   |――| |――| |――| |――| |  |   | 3 | | 3 | | 3 | |-4 | |  |   |――| |――| |――| |――| |――|   |////| |////| |////| |////| |////| (3)4509 CONST BELL   BELの値を4509とする。 (4)[ BEL-ON 0 BEL !B ]   キーを押したときベルを鳴らすようにするワードBEL−ONの定義   (POKE4509,0)。 (5)[ BEL-OF 1 BEL !B]   キーを押したときベルを鳴らさない(POKE4509,1)。 (6)M[ BYE $C3 0 0 ]M   モニタヘ戻る(JP $0000)ワードBYEの定義。 (7)[ BYE 0 USR ]   モニタヘ戻る(USR(0))。 (8)127 16 BASE ! DUP . 2 BASE ! DUP LF . #A BASE ! .   は次のように表示される。   ・――――――――――――――――――――・   | 表示:7F    (127の16進表示)  |   |    1111111 (127の2進表示)  |   |    127   (127の10進表示)  |   ・――――――――――――――――――――・ (9)[ TAB $1171 !B ]   カーソルのX座標をTOPの値にする。   10 TAB(ほばPRINT TAB(10);と同じ) (10)[ VTAB $1172 !B]   カーソルのY座標をTOPの値にする   (カーソルのX座標そのままで行を変える)。 (11)[ CUR VTAB TAB ]   カーソルを(2ND:x、TOP:y)に移す。        0  〜   39 X座標      0・―――――――・       |       |   Y座標||       | CRT画面の座標       |       |      24|       |       ・―――――――・ (12)20 10 CUR"ABC" S.   :カーソルを(20,10)に移し、ABCをそこから表示する。 (13)REG 1 * CONST AREG 2 + CONST BC REG 4 + CONST DE REG 6 + CONST HL   USRで使用するレジスタのアドレスを定義する。 (14)[ TEMPO AREG !B $41 USR ]   BASICのTEMP0に相当。   例)4 TEMPO (TEMPO 4)。 (15)[ MUSIC DE ! $30 USR DROP ]   BASICのMUSICに相当。   ただし、文字ストリングの最後は■(C8)でなければならない。   例)"A#BC1D-A■" MUSIC(MUSIC"A#BC1D-A")。 (16)[ FACT DUP IF DUP 1 - FACT * ELSE DROP 1 THEN ]   TOPをnとするとき、   n!=n×(n−1)×…×2×1を計算する。          /n!=n×(n−1)!(n>0)   n!の定義は \0!=1   /FACT(n)=nXFACT(n−1)(n>0)\   \FACT(0)=1               / (17)[ FACT 1 SWAP 1 + 1 DO I * LOOP ]:   FACTの別の定義(F=1:FORI=1TON:F=F*I:NEXTに相当)。 (18)[ WAIT BEGEIN GETKY END ]   キーが何か押されるまで待つ。 (19)[ WAITSP BEGIN GETKY $20 = END ]   [スペース]キーが押されるまで待つ。 (20)[ SIN 0 SWAP CORDR SWAP DROP ]   x z SIN(x*SIN(z*π/360))のように使う。 (21)[ COS 0 SWAP CORDR DROP ]   x z COS(x*COS(z*π/360))のように使う。 (22)0 0 79 49 LINE   擬似グラフィック座標(0,0)から(79,49)に線を引く。   BASICで(X1,Y1)から(X2,Y2)に   線を引くルーチンの一例(LINEはこれを機械語に直したものです)。   ・――――――――――――――――――・   |10 DX=X1-X2:DY=Y1-Y2:DA=ABS(DX) |   | :IF DA